package linkservice

import (
	"errors"
	"fmt"
	"time"
	"yunj/app/enum/linkenum"
	"yunj/pkg/global"
	"yunj/pkg/yunj/core/builder"
	"yunj/pkg/yunj/core/builder/builderconsts"
	"yunj/pkg/yunj/core/builder/builderdto"
	"yunj/pkg/yunj/core/builder/builderenum"
	"yunj/pkg/yunj/core/builder/form"
	"yunj/pkg/yunj/core/builder/form/button"
	"yunj/pkg/yunj/core/builder/form/field"
	"yunj/pkg/yunj/core/builder/table"
	"yunj/pkg/yunj/core/builder/table/col"
	"yunj/pkg/yunj/core/builder/table/col/action"
	"yunj/pkg/yunj/core/builder/table/deftoolbar"
	"yunj/pkg/yunj/core/builder/table/toolbar"
	"yunj/pkg/yunj/util"

	"yunj/app/dto"
	"yunj/app/model"
	"yunj/app/validator/client/linkvalidator"
	"yunj/pkg/yunj/app/enum/stateenum"

	"github.com/gin-gonic/gin"
	"github.com/worklz/go-validate"
	"gorm.io/gorm"
)

type linkPage struct {
}

var LinkPage *linkPage

// 列表构建器
func (s *linkPage) ListBuilder(ctx *gin.Context) *builder.Table {
	return builder.NewTable(ctx, "LinkList").
		State([]builderdto.TableState{
			{Code: stateenum.NORMAL, Title: "正常"},
			{Code: stateenum.RECYLE_BIN, Title: "回收站"},
		}).
		Page(false).
		Filter(func(t *builder.Table, state *builderdto.TableState) (fields []form.FieldInterface, err error) {
			fields = []form.FieldInterface{
				field.NewText("desc", "描述"),
			}
			return
		}).
		Toolbar(func(t *builder.Table, state *builderdto.TableState) (actions []toolbar.ActionInterface, err error) {
			actions = []toolbar.ActionInterface{
				toolbar.NewOpenPopup("add", "添加").SetClass("layui-icon-add-circle").
					SetUrl(util.BuildAdminUrl("/link/list/add")).SetAuth("yunj_link_list_add"),
			}
			if state.Code == stateenum.RECYLE_BIN {
				actions = append(actions,
					toolbar.NewAsyncEvent(builderenum.TABLE_EVENT_TYPE_NORMAL, "恢复正常").SetDropdown(true).SetAuth("yunj_link_list_normal"),
					toolbar.NewAsyncEvent(builderenum.TABLE_EVENT_TYPE_DELETED, "永久删除").SetDropdown(true).SetAuth("yunj_link_list_deleted"),
				)
			} else {
				actions = append(actions,
					toolbar.NewAsyncEvent(builderenum.TABLE_EVENT_TYPE_RECYLE_BIN, "移入回收站").SetDropdown(true).SetAuth("yunj_link_list_recyle_bin"),
				)
			}
			return
		}).
		DefaultToolbar([]deftoolbar.ActionInterface{
			deftoolbar.NewFilter(),
		}).
		Cols(func(t *builder.Table, state *builderdto.TableState) (cols []table.ColInterface, err error) {
			cols = []table.ColInterface{
				col.NewCheckbox("id", "ID"),
				col.NewDragSortIcon().SetAuth("yunj_link_list_sort"),
				col.NewText("link", "链接"),
				col.NewText("desc", "描述"),
				col.NewEnum("status", "状态").SetOptions(builder.GetEnumTableColOptions(linkenum.StatusEnum)).SetAlign(builderconsts.ALIGN_CENTER),
				col.NewDatetime("create_time", "发布时间"),
				col.NewDatetime("last_update_time", "上次修改时间"),
			}
			actionCol := col.NewAction("操作").SetOptions([]action.ActionInterface{
				action.NewOpenPopup("edit", "详情").SetClass("layui-icon-survey").SetUrl(util.BuildAdminUrl("/link/list/edit")).SetAuth("yunj_link_list_edit"),
			})
			if state.Code == stateenum.RECYLE_BIN {
				actionCol.Options = append(actionCol.Options,
					action.NewAsyncEvent(builderenum.TABLE_EVENT_TYPE_NORMAL, "恢复正常").SetDropdown(true).SetAuth("yunj_link_list_normal"),
					action.NewAsyncEvent(builderenum.TABLE_EVENT_TYPE_DELETED, "永久删除").SetDropdown(true).SetAuth("yunj_link_list_deleted").SetConfirmFormFields(field.NewTxt("tips", "确认删除？")),
				)
			} else {
				actionCol.Options = append(actionCol.Options,
					action.NewAsyncEvent(builderenum.TABLE_EVENT_TYPE_RECYLE_BIN, "移入回收站").SetDropdown(true).SetAuth("yunj_link_list_recyle_bin"),
				)
			}
			cols = append(cols, actionCol)
			return
		}).
		Validator(func(t *builder.Table) (validate.ValidatorInterface, error) {
			v := &linkvalidator.Link{}
			v.InitValidator(v)
			return v, nil
		}).
		Count(func(t *builder.Table, requestParam *builderdto.TableRequestParam) (res builderdto.TableCountResult, err error) {
			// 状态数量查询
			query := global.MySQL.Model(&model.Link{})
			var filterFormParam dto.AdminLinkPageListFilterFormParam
			util.MapToStruct(requestParam.FilterData(), &filterFormParam)
			s.listBuilderFilterQuery(query, requestParam, &filterFormParam)
			err = query.Count(&res.Count).Error
			if err != nil {
				err = fmt.Errorf("数据量查询异常！%v", err)
				return
			}
			return
		}).
		Items(func(t *builder.Table, requestParam *builderdto.TableRequestParam) (res builderdto.TableItemsResult, err error) {
			query := global.MySQL.Select("*")
			var filterFormParam dto.AdminLinkPageListFilterFormParam
			util.MapToStruct(requestParam.FilterData(), &filterFormParam)
			s.listBuilderFilterQuery(query, requestParam, &filterFormParam)
			if util.Float64ToUints(requestParam.State) != stateenum.RECYLE_BIN {
				query.Order("sort asc")
			} else {
				query.Order("last_update_time desc")
			}
			var dbItems []*model.Link
			if err = query.Find(&dbItems).Error; err != nil {
				err = fmt.Errorf("数据查询异常！%v", err)
				return
			}
			res.Items, err = s.listBuilderItemsHandle(dbItems)
			return
		}).
		Event(func(t *builder.Table, requestParam *builderdto.TableRequestParam) (res builderdto.TableEventResult, err error) {
			handleEventRes, err := builderenum.HandleEvent(ctx, &model.Link{}, requestParam.EventCode, requestParam.Pks, func(param *builderenum.EventDbParam, e *builderenum.Event, pks []any) (err error) {
				if _, exists := param.Data["updated_at"]; exists {
					param.Data["last_update_time"] = time.Now().In(time.Local).Unix()
					delete(param.Data, "updated_at")
				}
				return
			})
			if err != nil {
				return
			}
			if handleEventRes != nil {
				res.ResponseJsonData = handleEventRes
				return
			}
			err = fmt.Errorf("异常事件[%v]", requestParam.EventCode)
			return
		})
}

// 列表数据项处理
func (s *linkPage) listBuilderItemsHandle(items []*model.Link) (resItems []*dto.AdminLinkPageListItemResponse, err error) {
	if len(items) <= 0 {
		return
	}
	resItems = make([]*dto.AdminLinkPageListItemResponse, 0, len(items))
	for _, item := range items {
		resItem := &dto.AdminLinkPageListItemResponse{
			Id:             item.Id,
			Link:           item.Link,
			Desc:           item.Desc,
			Status:         item.Status,
			CreateTime:     item.CreateTime,
			LastUpdateTime: item.LastUpdateTime,
		}
		resItems = append(resItems, resItem)
	}
	return
}

// 列表过滤条件查询对象
func (s *linkPage) listBuilderFilterQuery(query *gorm.DB, requestParam *builderdto.TableRequestParam, filterFormParam *dto.AdminLinkPageListFilterFormParam) {
	// ids
	if len(requestParam.Pks) > 0 {
		query.Where("`id` in ?", requestParam.Pks)
	}
	// state
	stateWhere := stateenum.NORMAL
	if stateCode, ok := stateenum.IsValue(requestParam.State); ok {
		stateWhere = stateCode
	}
	query.Where("state = ?", stateWhere)
	// desc
	if filterFormParam.Desc != "" {
		keywordsWhere := "%" + filterFormParam.Desc + "%"
		query.Where("`desc` like ?", keywordsWhere)
	}
}

// 表单构建器
func (s *linkPage) FormBuilder(ctx *gin.Context, isEdit bool) (formBuilder *builder.Form) {
	formBuilder = builder.NewForm(ctx, "LinkForm").
		Field(func(f *builder.Form, tab *builderdto.FormTab) (fields []form.FieldInterface, err error) {
			fields = []form.FieldInterface{
				field.NewText("link", "链接").SetVerify("url"),
				field.NewTextarea("desc", "描述").SetVerify("chsDash|max:200").SetDesc("限制200字符数。只能输入汉字、字母、数字和下划线_及短横线-"),
				field.NewSwitch("status", "发布").SetOptions([]builderdto.Option{
					{Value: linkenum.STATUS_PUBLISH, Label: "是"},
					{Value: linkenum.STATUS_PENDING, Label: "否"},
				}),
			}
			if isEdit {
				fields = append(fields, field.NewHidden("id"))
			}
			// 设置栅格布局
			for _, v := range fields {
				v.SetFieldGrid([]any{12, 6, "6 l3 r3"})
			}
			return
		}).
		Button(func(f *builder.Form) (buttons []form.ButtonInterface, err error) {
			if isEdit {
				buttons = []form.ButtonInterface{
					button.NewReset(),
					button.NewSubmit(),
				}
			} else {
				buttons = []form.ButtonInterface{
					button.NewClear(),
					button.NewSubmit(),
				}
			}
			return
		}).
		Validator(func(f *builder.Form) (validate.ValidatorInterface, error) {
			v := &linkvalidator.Link{}
			v.InitValidator(v)
			return v, nil
		}).
		Submit(func(f *builder.Form, values map[string]any) (res builderdto.FormSubmitResult, err error) {
			var dbLink *model.Link
			dbLink = util.MapKeyValue(values, "dbLink", dbLink)
			if dbLink.Id > 0 {
				// 修改
				err = global.MySQL.Select("link", "desc", "status", "last_update_time").Save(dbLink).Error
				if err != nil {
					err = fmt.Errorf("编辑失败！%v", err.Error())
					return
				}
			} else {
				// 新增
				err = global.MySQL.Create(dbLink).Error
				if err != nil {
					err = fmt.Errorf("新增失败！%v", err.Error())
					return
				}
			}
			res.Reload = true
			return
		})

	if isEdit {
		formBuilder.Load(func(f *builder.Form) (res any, err error) {
			id := util.QueryUint64Param(ctx, "id")
			if id <= 0 {
				err = fmt.Errorf("异常数据")
				return
			}
			var data model.Link
			dbErr := global.MySQL.Where("`id` = ? and state <> ?", id, stateenum.DELETED).First(&data).Error
			if (dbErr != nil && !errors.Is(dbErr, gorm.ErrRecordNotFound)) || data.Id <= 0 {
				err = fmt.Errorf("数据获取异常！%v", dbErr)
				return
			}
			res = dto.AdminLinkPageFormLoadResponse{
				Id:     data.Id,
				Link:   data.Link,
				Desc:   data.Desc,
				Status: data.Status,
			}
			return
		})
	}
	return
}
